Project Name: Reflex Timer: The 5.00 Second Challenge
Category: Timing, Gaming, Advanced Input, Focus
What is it? This project is a test of your internal clock! After a countdown, the timer starts. Your mission is to focus and press the button as close as possible to exactly 5.00 seconds. Every millisecond counts!
What You Will Learn
By building this high-precision tester, you will learn to:
- Handle Timing States: Use different
GameStatemodes (Wait, Countdown, Timing) to control the flow of the game. - Use the Bounce Library: Make sure your button presses are accurate and reliable (no double-clicks!).
- Display Advanced Digits: Control a 4-digit 7-Segment Display (TM1650) to show the precise elapsed time.
- Calculate Precision: Use the ESP32 to track time down to the hundredth of a second (milliseconds).
Circuit Connections
This map shows you the physical map for building the project. It shows exactly where to plug in every wire for the buttons, LEDs, and screen so that the software instructions can correctly control all the hardware pieces.

| Component | ESP32 Dev Module | The Function |
| I2C LCD SDA/SCL | SDA/SCL | The screen shows instructions and the final verdict |
| TM1650 | SDA/SCL | This 4 digit display shows the time running down to 2 decimal places |
| Push Button | IO14 | Press this button to start and stop the timer |
| Buzzer | IO27 | Plays the countdown beep and celebration/fail tones |
| NEOPIXEL (RGB) | IO4 | Lights up blue when the timer starts and flashes the result color |
Code Lab
This section holds the instructions for the ESP32. It’s the “brain” that tells the board exactly what to do, like when to flash a green light, what sound to play, and how to choose a random card. You copy and upload this code so your project can actually work.

Step 1: Install Library
Before uploading the code, you need to install these libraries in Arduino IDE:
- LiquidCrystal_I2C.h by Frank de Brabander (for I2C LCD)
- Adafruit_Neopixel.h by Adafruit
- TM1650.h
- Bounce2.h by Thomas O Fredericks (For perfect button presses)
For example:

Step 2: Full Code
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>
#include <TM1650.h>
#include <Bounce2.h>
#define BUTTON_PIN 14
#define BUZZER_PIN 27
#define CLK 22
#define DIO 21
#define LED_PIN 4
#define NUM_LEDS 6
LiquidCrystal_I2C lcd(0x27, 16, 2);
TM1650 DigitalTube(CLK, DIO);
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
Bounce debouncer = Bounce();
enum GameState { WAIT_START, COUNTDOWN, TIMING, RESULT };
GameState state = WAIT_START;
unsigned long startMillis;
float currentTime;
bool resultShown = false;
void setup() {
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
debouncer.attach(BUTTON_PIN);
debouncer.interval(25);
lcd.init();
lcd.backlight();
TM1650 DigitalTube(CLK, DIO);
for (char i = 0; i < 4; i++) {
DigitalTube.clearBit(i);
}
strip.begin();
strip.show();
lcd.setCursor(0, 0);
lcd.print("Reflex Tester");
lcd.setCursor(0, 1);
lcd.print("Press to Start");
}
void loop() {
debouncer.update();
switch (state) {
case WAIT_START:
if (debouncer.fell()) {
lcd.clear();
lcd.print("Get Ready...");
state = COUNTDOWN;
delay(1000);
}
break;
case COUNTDOWN:
for (int i = 3; i > 0; i--) {
lcd.clear();
lcd.print("Starting in ");
lcd.print(i);
tone(BUZZER_PIN, 1000, 200);
delay(1000);
}
lcd.clear();
lcd.print("Go!");
strip.fill(strip.Color(0, 0, 255)); // Blue
strip.show();
startMillis = millis();
resultShown = false;
state = TIMING;
break;
case TIMING:
currentTime = (millis() - startMillis) / 1000.0;
if (currentTime <= 10.00) {
DigitalTube.displayFloatNum((int)(currentTime * 100));
} else {
showResult(false);
state = RESULT;
break;
}
if (debouncer.fell()) {
if (abs(currentTime - 5.00) <= 0.05) {
showResult(true);
} else {
showResult(false);
}
state = RESULT;
}
break;
case RESULT:
if (debouncer.fell()) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Press to Start");
for (char i = 0; i < 4; i++) {
DigitalTube.clearBit(i);
}
strip.clear();
strip.show();
state = WAIT_START;
}
break;
}
}
void showResult(bool success) {
lcd.clear();
resultShown = true;
if (success) {
lcd.print("Success!");
tone(BUZZER_PIN, 2000, 300);
ledPulse(strip.Color(0, 255, 0)); // Green
} else {
lcd.print("Too Slow/Fast");
tone(BUZZER_PIN, 400, 500);
ledFlash(strip.Color(255, 0, 0)); // Red
}
lcd.setCursor(0, 1);
lcd.print("Time: ");
lcd.print(currentTime, 2);
}
void ledPulse(uint32_t color) {
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, color);
}
strip.show();
delay(600);
strip.clear();
strip.show();
}
void ledFlash(uint32_t color) {
for (int i = 0; i < 3; i++) {
strip.fill(color);
strip.show();
delay(200);
strip.clear();
strip.show();
delay(200);
}
}
Step 3: Upload and Run
- Select your ESP32 board and the correct Port.
- Hit Upload and prepare your fastest hand!
How to Play

What is this all about?
This project, “The 5.00 Second Challenge,” is a precise electronic tool that tests your reaction time and internal clock. It’s a fun way to train your mind to be extremely focused and precise, measuring human error down to 1/100 of a second!
The benefits:
- Improve Focus: Challenges you to concentrate completely on the task, ignoring distractions.
- Boost Precision: Trains your motor skills and timing to hit a specific moment with high accuracy.
- Great Party Game: It’s an awesome, competitive challenge to see who among your friends has the steadiest hand and sharpest internal timer!
The reflex Timer is a precise three-step process:
1. Get Ready
- Initial Screen: The LCD displays:
Reflex Tester/Press to Start. - Start: Press the main button (GPIO14).
- Countdown: The LCD shows
Starting in 3... 2... 1...with countdown beeps from the buzzer.
2. The Challenge (Timing State)
- GO! The LCD says “Go!”, and the NeoPixel Strip lights up BLUE.
- The Timer: The 4-digit 7-segment display starts showing the time elapsed (e.g., 1.55,3.12,4.88, etc.).
- Your Goal: You must press the button as close as you can to 5.00 seconds!
3. The Result
The moment you press the button, the timer stops, and the result is displayed:
| Condition | LCD Message | NeoPixel Feedback | Sound |
| SUCCESS! (Within ±0.05s of 5.00) | Success! / Time: 5.00 | Flashes GREEN | A sharp, happy tone |
| FAILURE! (Too Fast, Too Slow, or Timeout) | Too Slow/Fast / Time: X.XX | Flashes RED | A low, sad failure tone |
| Timeout! (Takes longer than 10.00s) | Too Slow/Fast / Time: 10.00 | Flashes RED | A low, sad failure tone Export to Sheets |
4. Restarting
Press the button again when the result is displayed to reset the system and return to the Press to Start screen.
Troubleshooting Guide
This guide is your fast-fix manual for when errors occur. It helps you quickly diagnose why something isn’t working, like a dark screen or a silent buzzer—and provides simple steps to correct the problem.
| Problem | What is Happening? | Simple Solution to Try |
| Button is erratic or double-clicks. | This is a wiring issue, but the Bounce2 library usually fixes it. | Check Wiring: Ensure the button is securely wired from GPIO14 |
| LCD is blank / TM1650 is dark. | I2C communication or power is failing. | Check I2C Share: Ensure BOTH devices (LCD and TM1650) are correctly wired to GPIO21/22. |
| The 7-Segment Display (TM1650) is showing garbage. | The clock and data pins might be swapped. | Check Wiring: Double-check that CLK goes to SCK and DIO goes to SDA. |
| The NeoPixel strip won’t light up (GPIO4). | Power or Data pin connection is missing. | Check Data: Make sure Data In (DIN) is connected securely to GPIO4. |
| The buzzer is silent during the countdown. | The speaker is not connected correctly. | Check Wiring: Make sure the buzzer is correctly wired to GPIO27. |






